using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlClient;
using System.Data;

namespace Efficient.DataAccess.DbProvider
{
    [DbProvider(DbProviderType.SqlServer2005)]
    internal class SqlDbService : DbService, IDbService
    {
        private static readonly string computeRecordCountTemplate;
        private static readonly string pagingQueryTemplate;
        private static readonly string firstResultQueryTemplate;
        private const string ORDER_PLACE_HOLDER = "$Order$";
        private const string SELECT = "select ";
        
        static SqlDbService()
        {
            computeRecordCountTemplate = string.Concat("select count(*) from(", QUERY_TAG, ") __query");
            pagingQueryTemplate = string.Concat("select * from (select ROW_NUMBER()OVER(ORDER BY ", ORDER_PLACE_HOLDER, ") as [$row] ,a.* from (", QUERY_TAG, ") a ) __query where [$row] > ", START_PLACE_HOLDER, " and [$row] <= ", END_PLACE_HOLDER);
            firstResultQueryTemplate = string.Concat("select * from (select ROW_NUMBER()OVER(ORDER BY ", ORDER_PLACE_HOLDER, ") as [$row] ,a.* from (", QUERY_TAG, ") a ) __query where [$row] > ", START_PLACE_HOLDER);
        }

        public SqlDbService(string connectionString) : base(connectionString) { }

        public string ParamNamedPrefix
        {
            get { return "@"; }
        }

        public override IDbCommand CreateCommand()
        {
            return new SqlCommand();
        }

        public override IDbDataParameter CreateParameter()
        {
            return new SqlParameter();
        }

        public override IDbDataAdapter CreateDataAdapter()
        {
            return new SqlDataAdapter();
        }

        public override IDbConnection CreateConnection(string connectionString)
        {
            return new SqlConnection(connectionString);
        }

        protected override string ComputeRecordCountTemplate
        {
            get { return computeRecordCountTemplate; }
        }

        #region IDbService Members

        public bool SupportLimit
        {
            get { return true; }
        }

        public bool SupportLimitOffset
        {
            get { return true; }
        }

        public bool PagingNeedOrder
        {
            get { return true; }
        }

        public char CloseQuote
        {
            get { return ']'; }
        }

        public char OpenQuote
        {
            get { return '['; }
        }

        public string MaxResultQuery(string rawQuery, uint maxRow)
        {
            int selectIndex = rawQuery.IndexOf(SELECT, StringComparison.OrdinalIgnoreCase);
            return rawQuery.Insert(selectIndex + SELECT.Length, string.Concat("Top (", maxRow.ToString(), ") "));
        }

        public string BuildPagingResultQueryNeedOrder(string rawQuery, string orderString, string startParam, string endParam)
        {
            StringBuilder result = new StringBuilder(pagingQueryTemplate);
            result.Replace(ORDER_PLACE_HOLDER, orderString);
            result.Replace(QUERY_TAG, rawQuery);
            result.Replace(START_PLACE_HOLDER, startParam);
            result.Replace(END_PLACE_HOLDER, endParam);
            return result.ToString();
        }

        public string BuildFirstResultQueryNeedOrder(string rawQuery, string orderString, string startParam)
        {
            StringBuilder result = new StringBuilder(firstResultQueryTemplate);
            result.Replace(ORDER_PLACE_HOLDER, orderString);
            result.Replace(QUERY_TAG, rawQuery);
            result.Replace(START_PLACE_HOLDER, startParam);
            return result.ToString();
        }

        public string BuildPagingResultQuery(string rawQuery, string startParam, string endParam)
        {
            throw new NotImplementedException();
        }

        public string BuildFirstResultQuery(string rawQuery, string startParam)
        {
            throw new NotImplementedException();
        }

        #endregion

    }
}
